package com.hk.commons.poi.excel.read;

import com.hk.commons.poi.ReadException;
import com.hk.commons.poi.excel.exception.ExcelReadException;
import com.hk.commons.poi.excel.metadata.ReadWorkbook;
import com.hk.commons.util.StringUtils;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.apache.poi.poifs.filesystem.FileMagic;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Objects;


/**
 * @author Kevin
 */
@Getter
@RequiredArgsConstructor
public enum ExcelTypeEnum {


    /**
     * xls类型的Excel
     */
    XLS("xls"),

    /**
     * xlsx类型的Excel
     */
    XLSX("xlsx");

    private final String value;

    public static ExcelTypeEnum valueOf(ReadWorkbook readWorkbook) {
        var file = readWorkbook.getFile();
        var inputStream = readWorkbook.getInputStream();
        if (Objects.isNull(file) && Objects.isNull(inputStream)) {
            throw new ReadException("File and inputStream must be a non-null.");
        }
        try {
            if (Objects.nonNull(file)) {
                if (!file.exists()) {
                    throw new ReadException(STR."File \{file.getAbsolutePath()} not exists.");
                }
                // If there is a password, use the FileMagic first
                if (!StringUtils.isEmpty(readWorkbook.getPassword())) {
                    try (var bufferedInputStream = new BufferedInputStream(new FileInputStream(file))) {
                        return recognitionExcelType(bufferedInputStream);
                    }
                }
                // Use the name to determine the type
                var fileName = file.getName();
                if (fileName.endsWith(XLSX.getValue())) {
                    return XLSX;
                } else if (fileName.endsWith(XLS.getValue())) {
                    return XLS;
                }
                if (StringUtils.isEmpty(readWorkbook.getPassword())) {
                    try (var bufferedInputStream = new BufferedInputStream(new FileInputStream(file))) {
                        return recognitionExcelType(bufferedInputStream);
                    }
                }
            }
            return recognitionExcelType(inputStream);
        } catch (Exception e) {
            throw new ExcelReadException(
                    "Convert excel format exception.You can try specifying the 'excelType' yourself", e);
        }
    }

    @SneakyThrows
    private static ExcelTypeEnum recognitionExcelType(InputStream inputStream) {
        var fileMagic = FileMagic.valueOf(inputStream);
        if (FileMagic.OLE2.equals(fileMagic)) {
            return XLS;
        }
        if (FileMagic.OOXML.equals(fileMagic)) {
            return XLSX;
        }
        throw new ExcelReadException("Convert excel format exception.You can try specifying the 'excelType' yourself");
    }
}
